// Copyright (c) 1996-2002 John Lyon-Smith. All rights reserved.

#pragma once

#include <wxtl\SyncObject.h>

namespace wxtl
{
	class Process : public SyncObject
	{
	public:
		Process() throw()
		{
			memset(&m_si, 0, sizeof(m_si));
			m_si.cb = sizeof(m_si);
			
			memset(&m_pi, 0, sizeof(m_pi));
		}
		~Process()
		{
		}

		enum
		{
			// Options
			attrBreakAwayFromJob = CREATE_BREAKAWAY_FROM_JOB,
			attrDebugProcess = DEBUG_PROCESS,
			attrDebugOnlyThisProcess = DEBUG_ONLY_THIS_PROCESS,
			attrCreateSuspended = CREATE_SUSPENDED,
			attrDetachedProcess = DETACHED_PROCESS,                  
			attrNewConsole = CREATE_NEW_CONSOLE,
			attrNewProcessGroup = CREATE_NEW_PROCESS_GROUP,
			attrUnicodeEnvironment = CREATE_UNICODE_ENVIRONMENT,
			attrSeparateWowVdm = CREATE_SEPARATE_WOW_VDM,
			attrSharedWowVdm = CREATE_SHARED_WOW_VDM,             
			attrForceDos = CREATE_FORCEDOS,                   
			attrPreserveCodeAuthzLevel = CREATE_PRESERVE_CODE_AUTHZ_LEVEL,
			attrDefaultErrorMode = CREATE_DEFAULT_ERROR_MODE,
			attrNoWindow = CREATE_NO_WINDOW,

			// Priority
			priIdle = IDLE_PRIORITY_CLASS,               
			priBelowNormal = BELOW_NORMAL_PRIORITY_CLASS,
			priNormal = NORMAL_PRIORITY_CLASS,
			priAboveNormal = ABOVE_NORMAL_PRIORITY_CLASS,
			priHigh = HIGH_PRIORITY_CLASS,               
			priRealtime = REALTIME_PRIORITY_CLASS,           
		};

		virtual void create(
			const TCHAR* pszAppName, 
			LPTSTR pszCmdLine = NULL,
			const TCHAR* pszCurDir = NULL,
			LPVOID pEnv = NULL,
			DWORD createFlags = priNormal,
			BOOL bInherit = false,  
			LPSECURITY_ATTRIBUTES pProcessSecAttr = NULL, 
			LPSECURITY_ATTRIBUTES pThreadSecAttr = NULL,
			bool bKeepThreadHandle = false)	throw(_win32_error)
		{
			size_t szBuf = _tcslen(pszAppName) + (pszCmdLine != NULL ? _tcslen(pszCmdLine) : 0) + 4 * sizeof(TCHAR);
			scoped_array<TCHAR> bigBuf(new TCHAR[szBuf]);
		
			if (pszCmdLine != NULL)
				_stprintf_s(bigBuf.get(),szBuf, _T("\"%s\" %s"), pszAppName, pszCmdLine);
			else
				_stprintf_s(bigBuf.get(),szBuf, _T("\"%s\""), pszAppName);
			
			THROW_BAD_BOOL_RET(CreateProcess(
				NULL, bigBuf.get(), 
				pProcessSecAttr, pThreadSecAttr, 
				bInherit, createFlags, pEnv, pszCurDir, &m_si, &m_pi));
				
			m_h = m_pi.hProcess;
			
			if (!bKeepThreadHandle)
				CloseHandle(m_pi.hThread);
		}

		bool terminate(UINT uExitCode) throw()
		{
			return (TerminateProcess(m_pi.hProcess, uExitCode) == TRUE);
		}
		
		static void exit(UINT exitCode = 0) throw()
		{ 
			ExitProcess(exitCode); 
		}
		
		static void setCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, bool add = true) throw(...)
		{
			THROW_BAD_BOOL_RET(SetConsoleCtrlHandler(HandlerRoutine, add));
		}

	STARTUPINFO& getStartupInfo() { return m_si; }
	const PROCESS_INFORMATION&  getProcInfo() { return m_pi; }
	
	protected:		
		STARTUPINFO m_si;
		PROCESS_INFORMATION m_pi;
	};				
}
